package mainServer;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

/**
 *
 * @author Raman
 */
public class ChatServer implements Runnable {

  private ServerSocket server;
  private Socket fromClient;
  private Thread serverThread;
   
  /** Creates a ServerSocket at given port (4000) and starts the Server thread */
  public ChatServer() {

    try {
      server = new ServerSocket(4000);
      serverThread = new Thread(this);
      serverThread.start();
      System.out.println("Server Thread Started ....");
    } catch (Exception ex) {
      System.out.println("Cannot start the thread " + ex);
      ex.printStackTrace();
    }

  }//END of ChatServer 

  /**Starts the chatServer*/
  public static void main(String args[]) {
    ChatServer chatServer = new ChatServer();
  }

  @Override
  public void run() {
    try {
      while (true) {
        fromClient = server.accept();
        Connect conn = new Connect(fromClient);
      }
    } catch (Exception ex) {
      System.out.println("Exception ChatServer.run() " + ex);
    }

  }//End of RUN
}//End of ChatServer

/** Connects the Client to Server */
final class Connect {

  private String fileName = "C:\\Users\\DELL\\Desktop\\Users.txt";
  private ObjectOutputStream streamToClient = null;
  private boolean done = false;
  private BufferedReader streamFromClient = null;
  //Vector is used here to implement concurrency
  private static Vector messageList = null;
  private static Vector userList = null;
  private String msg = "";
  private final static String str = "userList";

  // Initializes vector 
  static {
    messageList = new Vector(1, 1); //initialCapacity = 1 , incrementInCapacity = 1
    userList = new Vector(1, 1);
    userList.addElement(str);
  }
  
  /** Handles the verification and validation of User Data. It takes ClientSocket
   *  as parameter and gets InputStream and OutputStream to send messages to Client  
   */
  public Connect(Socket inFromClient) {

    String clientMsg = "";
    String message = "";
    try {
      streamFromClient = new BufferedReader(new InputStreamReader(inFromClient.getInputStream()));
      streamToClient = new ObjectOutputStream(inFromClient.getOutputStream());
      clientMsg = streamFromClient.readLine();

      // Whether from Timer Class---------------------------------------------- 
      if (clientMsg.equals("From Timer")) {

        streamToClient.writeObject(messageList);
        streamToClient.writeObject(userList);

      } // Whether from Login Interface ---------------------------------------
      else if (clientMsg.equals("LoginInfo")) {

        clientMsg = streamFromClient.readLine();
        if (verify(clientMsg)) {
          System.out.println("Login Message From Client " + clientMsg);
          int index = clientMsg.lastIndexOf(":");
          String userName = clientMsg.substring(0, index);

          if (!(userList.indexOf(userName) > 0)) {
            streamToClient.writeObject("Welcome");
            userList.addElement(userName);
            System.out.println("UserList after Login " + userList);
          } else {
            streamToClient.writeObject("Login denied");
          }
        }else {
          streamToClient.writeObject("Invalid User");
        }

      } // Whether from registerInterface -------------------------------------
      else if (clientMsg.equals("RegisterInfo")) {
        clientMsg = streamFromClient.readLine();
        if (!(checkFile(clientMsg))) {
          streamToClient.writeObject("User Exists");
          
        }else{
          PrintStream p = new PrintStream(new FileOutputStream(fileName, true));
          p.println();
          p.println(clientMsg);
          p.close();
          streamToClient.writeObject("Registered");
        }
      } //Whether a log out request from user-------------------------------
      else if (clientMsg.equals("User Logout")) {

        String user = (String) streamFromClient.readLine();
        userList.removeElement(user);
        System.out.println("UserList after Logout " + userList);

        if (userList.size() == 1) {
          messageList.clear();
        }
        System.out.println("MessageList after Logout " + messageList);

      } //Whether a user message from the chat window-----------------------
      else {

        message += clientMsg;
        messageList.addElement((String) message);
        streamToClient.writeObject(messageList);
      }

    } //End of try BLOCK
    catch (Exception ex) {
      System.out.println("ChatServer.Connect() ");
      ex.printStackTrace();
    } //End of catch BLOCK 
    finally {
      try {
        inFromClient.close();
      } catch (IOException ex) {
        System.out.println("ChatServer.Connect().finally ");
        ex.printStackTrace();
      }
    } //END of finally

  }//END of Connect()

  /** Verifies if the file has the given username and password */
  boolean verify(String mesg) {
    try {
      RandomAccessFile file = new RandomAccessFile(fileName, "r");
      while ((file.getFilePointer()) != (int)file.length() ) {
        if (file.readLine().equals(mesg)) {
          return true;
        }
      }
      file.close();
    } catch (Exception ex) {
      System.out.println("From Verify " + ex);
    }
    return false ;
  }

  /** Checks for the Registration status of the user */
  boolean checkFile(String mesg) {
    RandomAccessFile file = null ;
    try {
      file = new RandomAccessFile(fileName, "rw");
      //Getting userName from  client
      String strFromFile = " ";
      String colon = ":";
      String userName = (String) mesg.substring(0, ((String) mesg).lastIndexOf(colon));

      while ((file.getFilePointer()) != (int) (file.length())) {
        strFromFile = file.readLine();
        int colIndex = ((String) strFromFile).lastIndexOf(colon);
        if (colIndex != (-1)) {
          String nameFromFile = (String) strFromFile.substring(0, colIndex);

          if (userName.equals(nameFromFile)) {
            return true ;
          }
        }
      }//End of while
      
    } catch (Exception ex) {
      System.out.println("From CheckFile " + ex);
      ex.printStackTrace();
    }finally {
      try {
        file.close();
      } catch (IOException ex) {
        System.out.println("Closing file " + ex);
        ex.printStackTrace();
      }
    }
    return false;
  }//End of ChkFile
}
